﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MonoGame;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace TunnelsOfDeath.Objects
{
    enum ControllerSource
    {
        KEYBOARD,
        GAMEPAD1,
        GAMEPAD2,
        GAMEPAD3,
        GAMEPAD4
    }

    enum PlayerAction
    {
        MOVEUP,
        MOVEDOWN,
        MOVELEFT,
        MOVERIGHT,
        NOTHING,
        GETUP,
        GETDOWN,
        GETLEFT,
        GETRIGHT
    }

    enum PlayerState
    {
        ONMAP,
        FINISHED,
        NOTONMAP
    }



    class Player : Sprite
    {

        private ControllerSource controller;
        private int pushTicker = 0;
        public PlayerState State { get; set; }

        public Player(
            int _textureID,
            Dictionary<Direction, Vector2> _animationTable,
            Dictionary<Direction,int> _animationFrames,
            ObjectType _type,
            Vector2 _position,
            double _dealy,
            ControllerSource _controllersource): base (_textureID,_animationTable,_animationFrames,_type,_position,_dealy)
        {
            controller = _controllersource;
            State = PlayerState.ONMAP;
        }

        public override void UpdatePosition(double _tag)
        {
            if (!CheckTag(_tag))
            {
                PlayerAction action = ReadAction();
                Vector2 nextPosition = GetProposedPosition(action);
                Sprite nextObject = Globals.Map[(int)nextPosition.X, (int)nextPosition.Y];

                if (action == PlayerAction.NOTHING)
                {
                    pushTicker = 0;
                    return;
                }

                if (
                        ((nextObject == null || nextObject.Type == ObjectType.dirt) ||
                        (nextObject.Type == ObjectType.crystal && nextObject.ObjectDirection != Direction.down))

                    )
                {



                        if (nextObject != null)
                        {
                            if (nextObject.Type == ObjectType.crystal)
                                Globals.MainPlayer.Scores++;

                            Globals.ObjectManager.UnregisterObject(nextObject);
                        }
                        else
                        {
                            pushTicker = 0;
                        }

                        if ((int)action < 4) {
                            MoveTo(nextPosition);
                        } else if (nextObject != null) {
                            WakeUpNeighbours(nextObject.position);
                        }

                    }
                    else if (nextObject is FallingDown)
                    {
                        pushTicker++;
                        if (pushTicker > 3 && nextObject.ObjectDirection == Direction.stopped && Globals.Map[(int)nextObject.position.X, (int)nextObject.position.Y + 1] != null)
                        {
                            Vector2 pushPosition = nextPosition - this.position;
                            pushPosition = nextObject.position + pushPosition;
                            if (pushPosition.Y == this.position.Y)
                            {
                                if (Globals.Map[(int)pushPosition.X, (int)pushPosition.Y] == null)
                                {

                                    nextObject.MoveTo(pushPosition);
                                    nextObject.CheckTag(_tag);

                                    if ((int)action < 4)
                                    {
                                        MoveTo(nextPosition);
                                    }


                                }
                            }
                        }
                        WakeUpNeighbours();
                    }
                    else
                    {
                        Collisions.HandleCollision(this, nextObject);
                    }



                }
           
        }

        private void WakeUpNeighbours(Vector2 _pos)
        {

            foreach (Vector2 item in GetAllFieldsAround())
            {
                if (Globals.Map[(int)_pos.X + (int)item.X, (int)_pos.Y + (int)item.Y] != null && Globals.PositionUpdate.IndexOf(Globals.Map[(int)_pos.X + (int)item.X, (int)_pos.Y + (int)item.Y]) == -1)
                {
                    Globals.Map[(int)_pos.X + (int)item.X, (int)_pos.Y + (int)item.Y].CheckTag(GetTag());
                    Globals.PositionUpdate.Add(Globals.Map[(int)_pos.X + (int)item.X, (int)_pos.Y + (int)item.Y]);
                }
            }
        
        }

        private Vector2 GetProposedPosition(PlayerAction _action)
        {
            switch (_action)
            {
                case PlayerAction.MOVEUP:
                    return position+new Vector2(0,-1);
                case PlayerAction.MOVEDOWN:
                    return position + new Vector2(0, 1);
                case PlayerAction.MOVELEFT:
                    return position+new Vector2(-1,0);;
                case PlayerAction.MOVERIGHT:
                    return position+new Vector2(1,0);;
                case PlayerAction.NOTHING:
                    return position+new Vector2(0,0);;
                case PlayerAction.GETUP:
                    return position+new Vector2(0,-1);;
                case PlayerAction.GETDOWN:
                    return position+new Vector2(0,1);;
                case PlayerAction.GETLEFT:
                    return position+new Vector2(-1,0);;
                case PlayerAction.GETRIGHT:
                    return position+new Vector2(1,0);;
            }

            throw new Exception("Unknown player action... I do not know how to proceed");
        }

        private PlayerAction ReadAction()
        {
            
            if (controller == ControllerSource.KEYBOARD)
            {
                KeyboardState keyboard = Keyboard.GetState();

                if (keyboard.IsKeyDown(Keys.LeftControl))
                {
                    if (keyboard.IsKeyDown(Keys.Up))
                    {
                        return PlayerAction.GETUP;
                    }

                    if (keyboard.IsKeyDown(Keys.Down))
                    {
                        return PlayerAction.GETDOWN;
                    }

                    if (keyboard.IsKeyDown(Keys.Left))
                    {
                        return PlayerAction.GETLEFT;
                    }

                    if (keyboard.IsKeyDown(Keys.Right))
                    {
                        return PlayerAction.GETRIGHT;
                    }
                }
                else
                {

                    if (keyboard.IsKeyDown(Keys.Up))
                    {
                        return PlayerAction.MOVEUP;
                    }

                    if (keyboard.IsKeyDown(Keys.Down))
                    {
                        return PlayerAction.MOVEDOWN;
                    }

                    if (keyboard.IsKeyDown(Keys.Left))
                    {
                        return PlayerAction.MOVELEFT;
                    }

                    if (keyboard.IsKeyDown(Keys.Right))
                    {
                        return PlayerAction.MOVERIGHT;
                    }
                }


            }

            if (controller == ControllerSource.GAMEPAD1)
            {
                GamePadState gamepad = GamePad.GetState(PlayerIndex.One);

                if (gamepad.Buttons.X == ButtonState.Pressed)
                {
                    if (gamepad.DPad.Up == ButtonState.Pressed)
                    {
                        return PlayerAction.GETUP;
                    }

                    if (gamepad.DPad.Down == ButtonState.Pressed)
                    {
                        return PlayerAction.GETDOWN;
                    }

                    if (gamepad.DPad.Left == ButtonState.Pressed)
                    {
                        return PlayerAction.GETLEFT;
                    }

                    if (gamepad.DPad.Right == ButtonState.Pressed)
                    {
                        return PlayerAction.GETRIGHT;
                    }
                }
                else
                {
                    if (gamepad.DPad.Up == ButtonState.Pressed)
                    {
                        return PlayerAction.MOVEUP;
                    }

                    if (gamepad.DPad.Down == ButtonState.Pressed)
                    {
                        return PlayerAction.MOVEDOWN;
                    }

                    if (gamepad.DPad.Left == ButtonState.Pressed)
                    {
                        return PlayerAction.MOVELEFT;
                    }

                    if (gamepad.DPad.Right == ButtonState.Pressed)
                    {
                        return PlayerAction.MOVERIGHT;
                    }
                }




            }


            return PlayerAction.NOTHING;
        }
    }
}
